package nginx

import (
	"io"
	"os"
	"strings"

	"gitee.com/bjf-fhe/apicat/notify"
	nginx_notifier "gitee.com/bjf-fhe/apicat/notify/nginx"
	"gitee.com/bjf-fhe/apicat/platform"
	"gitee.com/bjf-fhe/apicat/source"
	nginx_source "gitee.com/bjf-fhe/apicat/source/nginx"
	"gitee.com/bjf-fhe/apicat/utils"
	"github.com/extrame/tail"
	"github.com/pkg/errors"
	"github.com/spf13/pflag"
)

const defaultLogFormat = `
http {
	log_format   main  '$remote_addr [$time_local] "$request" $status_code';
}
`

type Config struct {
	NotifierConfig nginx_notifier.Config
	Config         string
	Format         string
}

func (h *Config) AddFlags(set *pflag.FlagSet) {
	set.StringVar(&h.NotifierConfig.Dest, "dest", "/etc/nginx/conf.d/iptabls", "写入结果的目标文件")
	set.Int64Var(&h.NotifierConfig.Interval, "interval", 5*60, "写入的最小间隔事件")
	set.StringVar(&h.NotifierConfig.WorkDir, "workdir", "", "重启命令的执行目录")
	set.StringVar(&h.NotifierConfig.Cmd, "cmd", "nginx -s reload", "重启nginx的命令")
	set.StringVar(&h.Config, "config", "", "Nginx配置文件")
	set.StringVar(&h.Format, "format", "main", "Nginx配置文件中的log format名称")
}

func (h *Config) GetNotifier(ncfg *notify.Config) (platform.Notifier, error) {
	var notifier nginx_notifier.Handler

	err := notifier.Init(ncfg, &h.NotifierConfig)
	return &notifier, err
}

func (h *Config) GetSource(fh platform.RootConfiger, tailMode bool) (source.Reader, error) {
	if fh.IsLocalFile() {

		var reader io.Reader
		var err error
		var nginxConfig io.Reader
		// Use nginx config file to extract format by the name
		if h.Config == "" {
			nginxConfig = strings.NewReader(defaultLogFormat)
		} else {
			var nginxConfigFile *os.File
			nginxConfigFile, err = os.Open(h.Config)
			if err != nil {
				err = errors.Wrap(err, "打开Nginx配置文件出错")
				return nil, err
			}
			nginxConfig = nginxConfigFile
			defer nginxConfigFile.Close()
		}

		if tailMode {

			var buf = &utils.BufWithNotify{}

			var t *tail.Tail

			t, err = tail.TailFile(fh.GetFileName(), tail.Config{Follow: true, Poll: true})

			if err == nil {
				//read the first line of csv
				var firstLine = <-t.Lines
				buf.Write([]byte(firstLine.Text + "\n"))
				go func() {
					for line := range t.Lines {
						buf.Write([]byte(line.Text + "\n"))
					}
				}()
				reader = buf
			} else {
				return nil, err
			}

		} else {
			reader, err = fh.OpenFile()
			if err != nil {
				return nil, err
			}
		}

		return nginx_source.NewReader(reader, nginxConfig, h.Format, fh.GetTimeFormat(), tailMode)
	}
	return nil, errors.New("no such file")
	// Read from STDIN and use log_format to parse log records
}

func (h *Config) Check() error {
	return nil
}

func init() {
	platform.Register("nginx", &Config{})
}
